#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>

/*
从信号量中读取，如果为0， 那么就表示可以往共享内存写入
写入之后，把信号量变为1，表示可以从里读
*/
int main(int argc, char const *argv[])
{
    int running = 1;
    int shid; // 共享内存id
    int semid; // 信号量id
    int value;
    void *sharem = NULL;
    struct sembuf sem_b;
    sem_b.sem_num = 0;
    sem_b.sem_flg = SEM_UNDO;
    if ((semid = semget((key_t)123456, 1, 0666|IPC_CREAT)) == -1) { // 创建1个信号集
        perror("创建信号集失败！");
        exit(EXIT_FAILURE);
    }
    if (semctl(semid, 0, SETVAL, 0) == -1) {// 将sem_num为0的信号设置值为0 可变参数 可以传入sembuf
        printf("信号量初始失败！");
        if (semctl(semid, 0, IPC_RMID, 0) != 0) {// 失败 那么就删除
            perror("semctl 失败");
        }
        exit(EXIT_FAILURE);
    }
    shid = shmget((key_t)654321, (ssize_t)2048, 0600|IPC_CREAT); // 
    if (shid == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    sharem = shmat(shid, NULL, 0);// 挂载共享内存到本进程 第二个参数NULL代表让操作系统帮我们定一个地址 第三个参数代表默认的权限
    if (sharem == NULL) {
        perror("shmat");
        exit(EXIT_FAILURE);
    }

    while (running) {
        printf("running!\n");
        sleep(1);
        if ((value = semctl(semid, 0, GETVAL)) == 1) { // 1 表示可读
            printf("read data operate\n");
            sem_b.sem_op = -1;
            printf("Server data:%s\n", sharem);
            if(semop(semid, &sem_b, 1) == -1) {
                // 失败
                fprintf(stderr, "semop 失败！\n");
                exit(EXIT_FAILURE);
            }
        }
        if (strcmp(sharem, "end") == 0) {
            running --;
        }
    }
    shmdt(sharem);
    if (shmctl(shid, IPC_RMID, NULL) !=0 ){
        perror("shmctl");
        exit(EXIT_FAILURE);
    }
    if (semctl(semid, 0, IPC_RMID) != 0) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }


    return 0;
}
